package mymyoux.ia
{
	

	public class NeuralNetwork
	{
		protected var _input:uint;
		protected var _output:uint;
		protected var _numLayers:uint;
		protected var _neuronsByLayer:uint;
		protected var _layers:Vector.<Layer>;
		public function NeuralNetwork(input:uint, output:uint, numLayers:uint, neuronsByLayer:uint)
		{
			_input = input;
			_output = output;
			_numLayers = numLayers;
			_neuronsByLayer = neuronsByLayer;
			_layers = new Vector.<Layer>(numLayers + 1, true);
			_layers[0] = new Layer(_neuronsByLayer, input);
			var i:uint;
		
			for(i=1; i<_numLayers ; i++)
			{
				_layers[i] = new Layer(_neuronsByLayer, neuronsByLayer);
			}
			
			_layers[i] = new Layer(output, neuronsByLayer);
		}
		public function setInput(...values):Vector.<Number>
		{
			var outputs:Vector.<Number>;
			outputs = new Vector.<Number>(values.length, true);
			var p:String;
			for(p in values)
			{
				outputs[p] = values[p];
			}
			var i:uint;
			for(i = 0; i<_layers.length; i++)
			{
				outputs = _layers[i].setInput(outputs);
			}
			return outputs;
		}
		static public function loadNeuralXML(xml:XML):NeuralNetwork
		{
			var n:NeuralNetwork = new NeuralNetwork(xml.data.input, xml.data.output, xml.data.numLayers, xml.data.neuronsByLayer);
			var p:String, r:String;
			for(p in xml.layer)
			{
				for(r in xml.layer[p].weights)
				{
					n.setLayer(Number(p), Number(r), Vector.<Number>(xml.layer[p].weights[r].toString().split("/")));
				}
			}
			return n;
		}
		public function setLayer(idLayer:uint, idNeuron:uint, weights:Vector.<Number>):void
		{
				_layers[idLayer].setWeigths(idNeuron, weights);
		}
		public function getXML():XML
		{
			var xml:XML = <root></root>;
			xml.data.input = _input;
			xml.data.output = _output;
			xml.data.numLayers = _numLayers;
			xml.data.neuronsByLayer = _neuronsByLayer;
			var i:uint;
			for(i = 0; i<_layers.length; i++)
			{
				xml.layers[i] = _layers[i].getXML();
			}
			return xml;
		}
		public function toString():String
		{
			return getXML().toXMLString();
		}

	}
}
class Layer
{
	protected var _neurons:Vector.<Neuron>;
	protected var _numInputs:uint;
	protected var _inputs:Vector.<Number>;
	protected var _count:uint;
	public function Layer(neurons:uint, numInputs:uint):void
	{
		_neurons = new Vector.<Neuron>(neurons, true);
		_numInputs = numInputs;
		var i:uint;
		for(i=0; i<neurons; i++)
		{
			_neurons[i] = new Neuron(numInputs);
		}
		_inputs = new Vector.<Number>(numInputs, true);
		_count = 0;
	}
	public function setWeigths(idNeuron:uint, weights:Vector.<Number>):void
	{
		_neurons[idNeuron].weights = weights;
	}
	public function setInput(value:Vector.<Number>):Vector.<Number>
	{
		var outputs:Vector.<Number> = new Vector.<Number>(_neurons.length, true);
		var p:String;
		for(p in _neurons)
		{
			outputs[p] = _neurons[p].addInput(value);
		}
		return outputs;
	}
	public function getXML():XML
	{
		var xml:XML = <layer></layer>;
		xml.weights = <weights></weights>;
		var i:uint;
		var w:Vector.<Number>;
		for(i=0; i<_neurons.length; i++)
		{
			xml.weights[i] = _neurons[i].weights.join("/");
		}
		 
		return xml;
	}
}
import mymyoux.utils.Maths;
class Neuron
{
	protected var _weights:Vector.<Number>;
	protected var _setup:Boolean;
	protected var _parameter:Number;
	public function Neuron(numInputs:uint, parameter:Number = 1):void
	{
		_weights = new Vector.<Number>(numInputs + 1, true);
		_setup = false;
		_parameter = parameter;
	}
	public function set weights(value:Vector.<Number>):void
	{
		_setup = true;
		///trace("Création weights : "+value);
		_weights = value;
	}
	public function get weights():Vector.<Number>
	{
		if(!_setup)
		{
			var p:String;
			for(p in _weights)
			{
				_weights[p] = Maths.randBetween(1,200);
			}
		}
		return _weights;
	}
	public function addInput(values:Vector.<Number>):Number
	{
		trace(values);
		if(!_setup)
		{
			var p:String;
			for(p in _weights)
			{
				_weights[p] = Maths.randBetween(1,200);
			}
			_setup = true;
		}
		var i:uint;
		var result:Number = - _weights[0];
		for(i=0; i<values.length; i++)
		{
			result += _weights[i + 1] * values[i];
		}
		return 1 / (1 + Math.E^(-result/_parameter));
	}
}